home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Programming / MuManual / C_Sources / MMUCacheTest.c < prev    next >
C/C++ Source or Header  |  1999-03-14  |  13KB  |  365 lines

  1. /*********************************************************
  2.  ** MMUCacheTest                                        **
  3.  ** test whether the pre/postDMA functions work         **
  4.  ** correctly                                           **
  5.  ** Version 0.25 14th Mar 1998                          **
  6.  ** THOR-Software, Thomas Richter                       **
  7.  *********************************************************/
  8.  
  9. /// Includes
  10. #include <exec/types.h>
  11. #include <exec/ports.h>
  12. #include <exec/io.h>
  13. #include <exec/memory.h>
  14. #include <exec/execbase.h>
  15. #include <mmu/mmubase.h>
  16.  
  17. #include <dos/dos.h>
  18. #include <dos/dosextens.h>
  19. #include <dos/filehandler.h>
  20.  
  21. #include <proto/exec.h>
  22. #include <proto/dos.h>
  23. #include <proto/mmu.h>
  24.  
  25. #include <string.h>
  26. #include <stdio.h>
  27. ///
  28. /// Defines
  29. #define REVISION 10
  30. #define STRINGVERSION "0.25"
  31. #define STRINGDATE "14.3.99"
  32. #define NUMARGS 1L
  33.  
  34. #define BUFSIZE (128L*1024L)
  35. #define MAJIK1 ('Test')
  36. #define MAJIK2 (0xaa55ff00)
  37. #define MAJIK3 (0x11223344)
  38. #define MAJIK4 ('THOR')
  39. #define RETRIES 64
  40. ///
  41. /// Statics
  42. struct MMUBase *MMUBase;
  43. extern struct DosLibrary *DOSBase;
  44. extern struct ExecBase *SysBase;
  45. struct MsgPort *ioport;
  46. struct IOStdReq *io;
  47. ///
  48. /// Prototypes
  49. void FlushLibs(void);
  50. int RunTests(char *devicename);
  51. int main(int argc,char **argv);
  52. int AccessDevice(void);
  53. ULONG CheckSum(ULONG *buf,ULONG size);
  54. ///
  55.  
  56. char version[]="$VER: MMUCacheTest " STRINGVERSION " (" STRINGDATE ") © THOR";
  57.  
  58. /// main
  59. int main(int argc,char **argv)
  60. {
  61. char *devicename;
  62. int len;
  63. int rc=0;
  64.  
  65.         FlushLibs();
  66.         printf( "MMUCacheTest " STRINGVERSION " (" STRINGDATE ") © THOR.\n"
  67.                 "Internal use only, no commercial use.\n");
  68.  
  69.         if ((argc<2) || (argc>3) || (!strcmp(argv[1],"?"))) {
  70.                 printf("\nThis program reads from your HD to check whether the\n"
  71.                        "cache control functions of the mmu.library work\n"
  72.                        "correctly. It does not write to the HD at all and won't\n"
  73.                        "harm your data.\n\n"
  74.                        "Usage: %s device_name: [nommu]\n\n",argv[0]);
  75.         } else {
  76.                 if (argc==2) {
  77.                         MMUBase=(struct MMUBase *)OpenLibrary(MMU_NAME,0);
  78.                 } else  MMUBase=0;
  79.  
  80.                 devicename=argv[1];
  81.                 len=strlen(devicename);
  82.                 if (devicename[len-1]!=':') {
  83.                         printf("The device name must be given with a colon at the\n"
  84.                                "end, e.g. DH0:\n\n");
  85.                         rc=5;
  86.                 } else {
  87.                         devicename[len-1]=0;
  88.                         rc=RunTests(devicename);
  89.                 }
  90.  
  91.                 if (MMUBase)    CloseLibrary((struct Library *)MMUBase);
  92.         }
  93.  
  94.         return rc;
  95. }
  96. ///
  97. /// RunTests
  98. int RunTests(char *devicename)
  99. {
  100. struct DosList *dl;
  101. struct DosEnvec *env;
  102. struct FileSysStartupMsg *fstart;
  103. char *devname;
  104. int len;
  105. ULONG unit,flags;
  106. char device[256];
  107. BOOL locked=TRUE;
  108. int rc=10;
  109.  
  110.         if (dl=LockDosList(LDF_DEVICES|LDF_READ)) {
  111.                 if (dl=FindDosEntry(dl,devicename,LDF_DEVICES|LDF_READ)) {
  112.                         fstart=BADDR(dl->dol_misc.dol_handler.dol_Startup);
  113.                         if (TypeOfMem(fstart)) {
  114.                                 if (fstart->fssm_Unit<0x400) {
  115.                                         env=BADDR(fstart->fssm_Environ);
  116.                                         if (TypeOfMem(env)) {
  117.                                                 unit=fstart->fssm_Unit;
  118.                                                 flags=fstart->fssm_Flags;
  119.                                                 devname=BADDR(fstart->fssm_Device);
  120.                                                 if (TypeOfMem(devname)) {
  121.                                                         len=devname[0];
  122.                                                         memcpy(device,devname+1,len);
  123.                                                         device[len]=0;
  124.  
  125.                                                         UnLockDosList(LDF_DEVICES|LDF_READ);
  126.                                                         locked=FALSE;
  127.  
  128.                                                         if (ioport=CreateMsgPort()) {
  129.                                                                 if (io=(struct IOStdReq *)CreateIORequest(ioport,sizeof(struct IOStdReq))) {
  130.                                                                         if (!OpenDevice(device,unit,(struct IORequest *)io,flags)) {
  131.                                                                                 rc=AccessDevice();
  132.                                                                                 CloseDevice((struct IORequest *)io);
  133.                                                                         } else  printf("Failed to open the %s.\n",device);
  134.                                                                         DeleteIORequest((struct IORequest *)io);
  135.                                                                 } else printf("Failed to allocate the IORequest.\n");
  136.                                                                 DeleteMsgPort(ioport);
  137.                                                         } else printf("Failed to create the IO message port.\n");
  138.                                                 } else rc=5;
  139.                                         } else rc=5;
  140.                                 } else rc=5;
  141.                         } else rc=5;
  142.  
  143.                         if (rc==5) {
  144.                                 printf("The selected device is not a direct block I/O device.\n"
  145.                                        "Please specify a FAST DMA device for testiing.\n");
  146.                         }
  147.                 } else printf("Sorry, %s: is either not mounted or not a device.\n"
  148.                               "Please DO NOT specify volumes or assigns.\n",devicename);
  149.  
  150.                 if (locked)
  151.                         UnLockDosList(LDF_DEVICES|LDF_READ);
  152.  
  153.         }
  154.  
  155.         return rc;
  156. }
  157. ///
  158. /// AccessDevice
  159. int AccessDevice(void)
  160. {
  161. ULONG *buffer;
  162. UBYTE *mem;
  163. int i;
  164. int error;
  165. ULONG sum;
  166. ULONG discount;
  167. ULONG accesscount;
  168. volatile ULONG check,*ptr,*ptr2; /* make sure these are really read */
  169. long pri;
  170. ULONG mask;
  171.  
  172.         /* Allocate memory aligned to cache line boundaries */
  173.  
  174.         mem=AllocMem(BUFSIZE+16*3,MEMF_PUBLIC);
  175.         if (!mem) {
  176.                 printf("Out of memory, sorry!\n");
  177.                 return 20;
  178.         }
  179.         buffer=(ULONG *)(((ULONG)(mem+15)) & 0xfffffff0);
  180.  
  181.         if (MMUBase) {
  182.                 printf("mmu.library loaded.\n");
  183.         } else  printf("mmu.library not utilized.\n");
  184.  
  185.         /* Fill in some magic stuff */
  186.         ptr=buffer;
  187.         ptr2=buffer+8+BUFSIZE;  /* to the end of the buffer */
  188.         buffer[0]=MAJIK1;
  189.         buffer[1]=MAJIK2;
  190.         buffer[2]=MAJIK3;
  191.         buffer[3]=MAJIK4;
  192.         CacheClearU();
  193.         /* Make sure the stuff is really in memory */
  194.  
  195.         printf("Initial read, calculate checksum.\n");
  196.         io->io_Command=CMD_READ;
  197.         io->io_Length=BUFSIZE;
  198.         io->io_Offset=0;             /* well, whereever... this doesn't really matter... */
  199.         io->io_Data=buffer;
  200.         error=DoIO((struct IORequest *)io);
  201.         if (error) {
  202.                 printf("Can't read from the device, failure code %ld.\n",error);
  203.                 goto error;             /* bah! */
  204.         }
  205.         sum=CheckSum(buffer,BUFSIZE>>2);
  206.  
  207.         printf("\nRunning the initial device test.\n"
  208.                "This test checks whether the connected device works reliable.\n"
  209.                "It does NOT check the MMU code which is not needed for this\n"
  210.                "initial run.\n"
  211.                "This test SHOULD NOT fail. In case it does, your device or\n"
  212.                "host adapter is broken, but not the MMU logic.\n\n"
  213.                "In case you're running any disk cache program, e.g. DynamiCache,\n"
  214.                "you should disable it for this test. The test won't test anything\n"
  215.                "if any kind of disk cache is active!\n\n");
  216.  
  217.         for(i=0;i<RETRIES;i++) {
  218.                 /* For general entertainment, read data from somewhere else.
  219.                    This should hopefully disable caching of the device. */
  220.                 io->io_Command=CMD_READ;
  221.                 io->io_Length=BUFSIZE;
  222.                 io->io_Offset=800L*1024L;       /* well, whereever... this doesn't really matter... */
  223.                 io->io_Data=buffer;
  224.                 error=DoIO((struct IORequest *)io);
  225.                 if (error) {
  226.                         printf("Can't read from the device, failure code %ld.\n",error);
  227.                         goto error;             /* bah! */
  228.                 }
  229.  
  230.                 buffer[0]=MAJIK1;
  231.                 buffer[1]=MAJIK2;
  232.                 buffer[2]=MAJIK3;
  233.                 buffer[3]=MAJIK4;
  234.                 CacheClearU();
  235.                 /* Make sure the stuff is really in memory */
  236.                 io->io_Command=CMD_READ;
  237.                 io->io_Length=BUFSIZE;
  238.                 io->io_Offset=0;
  239.                 io->io_Data=buffer;
  240.                 error=DoIO((struct IORequest *)io);
  241.                 if (error) {
  242.                         printf("Can't read from the device, failure code %ld.\n",error);
  243.                         goto error;             /* bah! */
  244.                 }
  245.                 if (sum!=CheckSum(buffer,BUFSIZE>>2)) {
  246.                         printf("FATAL ERROR: Device read does not work reliable!\n"
  247.                                "Test failed. Looks like your hardware is broken, sorry.\n");
  248.                         goto error;
  249.                 }
  250.         }
  251.         printf("The initial test passed.\n");
  252.  
  253.         accesscount=0;
  254.         discount=0;
  255.  
  256.         printf("\nRunning the real test. If this test fails, something is wrong\n"
  257.                "with the CachePreDMA/CachePostDMA logic. In this case, please\n"
  258.                "sent me an EMail so I can fix it.\n");
  259.  
  260.         for(i=0;i<RETRIES;i++) {
  261.                 /* For general entertainment, read data from somewhere else.
  262.                    This should hopefully disable caching of the device. */
  263.                 io->io_Command=CMD_READ;
  264.                 io->io_Length=BUFSIZE;
  265.                 io->io_Offset=800L*1024L;       /* well, whereever... this doesn't really matter... */
  266.                 io->io_Data=buffer;
  267.                 error=DoIO((struct IORequest *)io);
  268.                 if (error) {
  269.                         printf("Can't read from the device, failure code %ld.\n",error);
  270.                         goto error;             /* bah! */
  271.                 }
  272.  
  273.                 /* start at a non-aligned address */
  274.                 io->io_Command=CMD_READ;
  275.                 io->io_Length=BUFSIZE;
  276.                 io->io_Offset=0;
  277.                 io->io_Data=buffer+8;
  278.  
  279.                 mask=(1<<i)-1;
  280.  
  281.                 pri=SetTaskPri(FindTask(NULL),1);
  282.  
  283.                 CacheClearU();
  284.                 /* Push some stuff into the cache */
  285.                 buffer[0]=MAJIK1;
  286.                 buffer[1]=MAJIK2;
  287.                 buffer[2]=MAJIK3;
  288.                 buffer[3]=MAJIK4;
  289.  
  290.                 /* Now start the IO, asynchronously */
  291.                 SendIO((struct IORequest *)io);
  292.                 while (((UBYTE)(SysBase->IDNestCnt))!=0xff || ((UBYTE)(SysBase->TDNestCnt))!=0xff) {
  293.                         Delay(2L);
  294.                         discount++;
  295.                 }
  296.  
  297.                 /* access the memory while the IO is active */
  298.                 while(!CheckIO((struct IORequest *)io)) {
  299.                         check=*ptr;
  300.                         check=*ptr2;
  301.                         accesscount++;
  302.                         if ((accesscount & mask)==0) {
  303.                                 (*ptr)++;
  304.                                 (*ptr2)++;
  305.                         }
  306.                 }
  307.  
  308.                 SetTaskPri(FindTask(NULL),pri);
  309.  
  310.                 error=WaitIO((struct IORequest *)io);
  311.                 if (error) {
  312.                         printf("Can't read from the device, failure code %ld.\n",error);
  313.                         goto error;             /* bah! */
  314.                 }
  315.                 if (sum!=CheckSum(buffer+8,BUFSIZE>>2)) {
  316.                         printf("The MMU cache test failed. There seems to be a bug in\n"
  317.                                "the CachePre/PostDMA functions. Please let me know!\n\n");
  318.                         goto error;
  319.                 }
  320.         }
  321.         printf("The MMU cache test passed.\n"
  322.                "Task switching was disabled %ld times, run %lu RAM accesses.\n",discount,accesscount);
  323.         Delay(100L);
  324.  
  325.         FreeMem(mem,BUFSIZE+16*3);
  326.         return 0;
  327.  
  328. error:
  329.         FreeMem(mem,BUFSIZE+16*3);
  330.         return 10;
  331. }
  332. ///
  333. /// CheckSum
  334. /* Calculate a hopefully somewhat useable checksum for the buffer. Size
  335.    is in long words */
  336. ULONG CheckSum(ULONG *buf,ULONG size)
  337. {
  338. ULONG sum=0;
  339.  
  340.         while(size) {
  341.                 sum += *buf;
  342.                 sum ^= size;
  343.                 if (sum & 0x01) {
  344.                         sum >>= 1;
  345.                         sum |= 0x80000000;
  346.                 } else  sum >>= 1;
  347.  
  348.                 buf++;
  349.                 size--;
  350.         }
  351.  
  352.         return sum;
  353. }
  354. ///
  355. /// FlushLibs
  356. void FlushLibs(void)
  357. {
  358. void *mem;
  359.  
  360.         if (mem=AllocMem(0x7ffffff0,MEMF_PUBLIC))
  361.                 FreeMem(mem,0x7ffffff0);
  362. }
  363. ///
  364.  
  365.